#include "mb_mw.h"

/* CMC设备 和 STO设备 的操作函数, 状态, 名字 */
cmc_op_status s_cmc_op_status[CMC_SELECT_MAX_NBR];
sto_op_status s_sto_op_status[STO_SELECT_MAX_NBR];

/* 中间件对数据处理的具体实现操作 */
prot_op_status s_prot_op_status[PROT_SELECT_MAX_NBR];
store_op_status s_store_op_status;

/* 人机交互 */
hci_op_status s_hci_op_status;

/* 中间件私有数据 */
mw_prvt s_mw_prvt = 
{
    .protsel = {PROT_UNKNOWN_DEF, MB_FALSE_DEF, CMC_UNKNOWN_DEF, MB_FALSE_DEF},
    .stosel  = {STO_UNKNOWN_DEF, MB_FALSE_DEF},
    .hcisel  = {CMC_UNKNOWN_DEF, MB_FALSE_DEF},
};

/* ======================================================================= */

/* 注册所有设备的操作函数 */
static int mb_mw_dev_op_register(void)
{
    int       i;
    MB_STATUS is_atleast_1_cmc = MB_FALSE;
    MB_STATUS is_atleast_1_sto = MB_FALSE;

    /* 指定 要用到的 CMC 设备 (支持多个设备同时在 MBOOT中使用) */
    CMC_SELECT CMCSEL[CMC_SELECT_MAX_NBR] = CMC_DEV_SELS_CFG;

    /* 指定 要用到的 CMC 设备 (支持多个设备同时在 MBOOT中使用) */
    STO_SELECT STOSEL[STO_SELECT_MAX_NBR] = STO_DEV_SELS_CFG;

    /* 注册所有选择的 CMC 设备操作函数 */
    for (i = 0; i < CMC_SELECT_MAX_NBR; i++)
    {
        /* 未知设备直接跳过 */
        if (CMCSEL[i] >= CMC_UNKNOWN_DEF)
        {
            s_cmc_op_status[i].is_can_use = MB_FALSE;
            continue;
        }

        /* 注册设备操作函数 */
        s_cmc_op_status[i].op = mb_cmc_op_register(CMCSEL[i]);

        if (s_cmc_op_status[i].op == NULL)
        {
            s_cmc_op_status[i].is_can_use = MB_FALSE;
            continue;
        }
        else
        {
            s_cmc_op_status[i].is_can_use = MB_TRUE;

            /* 至少有个 CMC设备 可用 */
            is_atleast_1_cmc = MB_TRUE;
        }

        /* 设置对应的名字 */
        CMC_DEV_NAME_SET(CMCSEL[i], s_cmc_op_status[i].name);
    }

    /* 注册所有选择的 STO 设备操作函数 */
    for (i = 0; i < STO_SELECT_MAX_NBR; i++)
    {
        /* 未知设备直接跳过 */
        if (STOSEL[i] >= STO_UNKNOWN_DEF)
        {
            s_sto_op_status[i].is_can_use = MB_FALSE;
            continue;
        }

        /* 注册设备操作函数 */
        s_sto_op_status[i].op = mb_sto_op_register(STOSEL[i]);

        if (s_sto_op_status[i].op == NULL)
        {
            s_sto_op_status[i].is_can_use = MB_FALSE;
            continue;
        }
        else
        {
            s_sto_op_status[i].is_can_use = MB_TRUE;

            /* 至少有个 STO设备 可用 */
            is_atleast_1_sto = MB_TRUE;
        }

        /* 设置对应的名字 */
        STO_DEV_NAME_SET(STOSEL[i], s_sto_op_status[i].name);
    }

    /* 判断设备操作函数注册结果 (CMC设备和STO设备至少各有一个函数操作注册成功) */
    if ((is_atleast_1_cmc == MB_FALSE) || (is_atleast_1_sto == MB_FALSE))
    {
        return -1;
    }

    return 0;
}

/* 注册数据协议的操作函数 */
static int mb_mw_prot_op_register(void)
{
    int       i;
    MB_STATUS is_atleast_1_prot = MB_FALSE;
    
    /* 指定 要用到的 PROT 数据协议 */
    PROT_SELECT PROTSEL[PROT_SELECT_MAX_NBR] = PROT_SELS_CFG;

    /* 注册所有选择的 PROT 数据协议操作函数 */
    for (i = 0; i < PROT_SELECT_MAX_NBR; i++)
    {
        /* 未知协议直接跳过 */
        if (PROTSEL[i] >= PROT_UNKNOWN_DEF)
        {
            s_prot_op_status[i].is_can_use = MB_FALSE;
            continue;
        }

        /* 注册协议操作函数 */
        s_prot_op_status[i].op = mb_prot_op_register(PROTSEL[i]);

        if (s_prot_op_status[i].op == NULL)
        {
            s_prot_op_status[i].is_can_use = MB_FALSE;
            continue;
        }
        else
        {
            s_prot_op_status[i].is_can_use = MB_TRUE;

            /* 至少有个 协议 可用 */
            is_atleast_1_prot = MB_TRUE;
        }

        /* 设置对应的名字 */
        PROT_NAME_SET(PROTSEL[i], s_prot_op_status[i].name);
    }

    /* 判断数据协议操作函数注册结果 (至少有一种协议的操作函数被注册) */
    if (is_atleast_1_prot == MB_FALSE)
    {
        return -1;
    }

    return 0;
}

/* 注册数据存储的操作函数 */
static int mb_mw_store_op_register(void)
{
    /* 注册存储操作函数 */
    s_store_op_status.op = mb_store_op_register();

    if (s_store_op_status.op == NULL)
    {
        s_store_op_status.is_can_use = MB_FALSE;
        return -1;
    }
    else
    {
        s_store_op_status.is_can_use = MB_TRUE;
    }

    return 0;
}

/* 注册人机交互的操作函数 */
static int mb_mw_hci_op_register(void)
{
    /* 注册人机交互操作函数 */
    s_hci_op_status.op = mb_hci_op_register();

    if (s_hci_op_status.op == NULL)
    {
        s_hci_op_status.is_can_use = MB_FALSE;
        return -1;
    }
    else
    {
        s_hci_op_status.is_can_use = MB_TRUE;
    }

    return 0;
}

/* =============== prot 和 store 作为mboot和具体实现的中间转接 =============== */

/* -------------------------- 数据协议转接函数 ------------------------------ */

/* 选择协议解析类型 */
static MB_STATUS mw_prot_op_prot_select(PROT_SELECT sel);
/* 选择数据载体 (即选择数据传输的通道) */
static MB_STATUS mw_prot_op_carrier_select(CMC_SELECT sel);
/* 帧解析出有效数据 */
static mb_buf_attr * mw_prot_op_transfer_and_parse(void);
/* 获得数据传输状态 */
static MB_XFR_STATUS mw_prot_op_get_xfr_status(void);

/* 数据协议操作函数 (作为mboot和具体实现的中间转接) */
mw_prot_op s_mw_prot_op = 
{
    .prot_select        = mw_prot_op_prot_select,
    .carrier_select     = mw_prot_op_carrier_select,
    .transfer_and_parse = mw_prot_op_transfer_and_parse,
    .get_xfr_status     = mw_prot_op_get_xfr_status,
};

/* 选择协议解析类型 */
static MB_STATUS mw_prot_op_prot_select(PROT_SELECT sel)
{
    /* 判断所选协议是否可用 */
    if (s_prot_op_status[sel].is_can_use != MB_TRUE)
    {
        return MB_FALSE;         /* 所选协议不可用 */
    }

    /* 相同的选择执行一次 */
    if (s_mw_prvt.protsel.prot_select != sel)
    {
        /* 记录选择 */
        s_mw_prvt.protsel.prot_select = sel;
        /* 标记已经设置选择 */
        s_mw_prvt.protsel.is_prot_set = MB_TRUE;
        return MB_TRUE;
    }

    return MB_FALSE;
}

/* 选择数据载体 (即选择数据传输的通道) */
static MB_STATUS mw_prot_op_carrier_select(CMC_SELECT sel)
{
    /* 先判断是否已选择协议 */
    if (s_mw_prvt.protsel.is_prot_set != MB_TRUE)
    {
        return MB_FALSE;    /* 没有选择协议 */
    }

    /* 判断数据载体是否可用 */
    if (s_cmc_op_status[sel].is_can_use != MB_TRUE)
    {
        return MB_FALSE;    /* 数据载体不可用 */
    }

    /* 相同的选择执行一次 */
    if (s_mw_prvt.protsel.cmc_select != sel)
    {
        /* 为协议指定数据载体并初始化数据载体 (硬件操作方法) */
        s_prot_op_status[s_mw_prvt.protsel.prot_select].op->carrier_init(s_cmc_op_status[sel].op);
        /* 记录选择 */
        s_mw_prvt.protsel.cmc_select = sel;
        /* 标记已经设置选择 */
        s_mw_prvt.protsel.is_cmc_set = MB_TRUE;
    }
    else
    {
        return MB_FALSE;
    }

    return MB_TRUE;
}

/* 帧解析出有效数据 */
static mb_buf_attr * mw_prot_op_transfer_and_parse(void)
{
    /* 判断数据协议和数据载体是否选择 */
    if ((s_mw_prvt.protsel.is_prot_set != MB_TRUE) || \
        (s_mw_prvt.protsel.is_cmc_set != MB_TRUE))
    {
        return NULL;    /* 没有选择数据协议或数据载体 */
    }

    /* 根据选择的协议, 执行对应的解析函数 */
    return s_prot_op_status[s_mw_prvt.protsel.prot_select].op->transfer_and_parse();
}

/* 获得数据传输状态 */
static MB_XFR_STATUS mw_prot_op_get_xfr_status(void)
{
    /* 判断数据协议和数据载体是否选择 */
    if ((s_mw_prvt.protsel.is_prot_set != MB_TRUE) || \
        (s_mw_prvt.protsel.is_cmc_set != MB_TRUE))
    {
        return NULL;    /* 没有选择数据协议或数据载体 */
    }

    /* 根据选择的协议, 执行对应的解析函数 */
    return s_prot_op_status[s_mw_prvt.protsel.prot_select].op->get_xfr_status();
}

/* -------------------------- 数据存储转接函数 ------------------------------ */

/* 选择数据载体 (即选择数据存储的通道) */
static MB_STATUS mw_store_op_carrier_select(STO_SELECT sel, uint32_t size);
/* 获得存储操作选择的数据载体类型 */
static STO_SELECT mw_store_op_get_carrier_select(void);
/* 保存 (存入) 固件 */
static MB_XFR_STATUS mw_store_op_store_firmware(mb_buf_attr * buf_attr);
/* 读出固件 */
static mb_buf_attr * mw_store_op_get_firmware(void);
/* 保存固件大小 (字节)  */
static void mw_store_op_store_firmware_size(void);
/* 获得固件大小 (字节) */
static uint32_t mw_store_op_get_firmware_size(void);


/* 数据存储操作函数 (作为mboot和具体实现的中间转接) */
mw_store_op s_mw_store_op = 
{
    .carrier_select      = mw_store_op_carrier_select,
    .get_carrier_select  = mw_store_op_get_carrier_select,
    .store_firmware      = mw_store_op_store_firmware,
    .get_firmware        = mw_store_op_get_firmware,
    .store_firmware_size = mw_store_op_store_firmware_size,
    .get_firmware_size   = mw_store_op_get_firmware_size,
};

/* 选择数据载体 (即选择数据存储的通道) */
static MB_STATUS mw_store_op_carrier_select(STO_SELECT sel, uint32_t size)
{
    /* 判断数据载体是否可用 */
    if (s_sto_op_status[sel].is_can_use != MB_TRUE)
    {
        return MB_FALSE;
    }

    /* 相同的选择执行一次 */
    if (s_mw_prvt.stosel.select != sel)
    {
        /* 为数据存储指定数据载体 (硬件操作方法) */
        s_store_op_status.op->carrier_init(s_sto_op_status[sel].op);

        /* 从载体中获得指定大小的空闲空间 (已被擦除过) */
        if (size != 0)
        {
            /* size != 0 时表示, 需要从 载体中获得一片空闲空间 */
            s_store_op_status.op->take_free_space(size);
        }

        /* 记录选择 */
        s_mw_prvt.stosel.select = sel;
        /* 标记已经设置选择 */
        s_mw_prvt.stosel.is_set = MB_TRUE;
        return MB_TRUE;
    }

    return MB_FALSE;
}

/* 获得存储操作选择的数据载体类型 */
static STO_SELECT mw_store_op_get_carrier_select(void)
{
    if (s_mw_prvt.stosel.is_set != MB_TRUE)
    {
        return STO_UNKNOWN;    /* 没有选择存储设备 */
    }

    return s_mw_prvt.stosel.select;
}

/* 保存 (存入) 固件 */
static MB_XFR_STATUS mw_store_op_store_firmware(mb_buf_attr * buf_attr)
{
    if (s_mw_prvt.stosel.is_set != MB_TRUE)
    {
        return MB_XFR_MODERR;    /* 没有选择存储设备 */
    }

    /* 执行存入固件 */
    return s_store_op_status.op->store_firmware(buf_attr);
}

/* 读出固件 */
static mb_buf_attr * mw_store_op_get_firmware(void)
{
    if (s_mw_prvt.stosel.is_set != MB_TRUE)
    {
        return NULL;    /* 没有选择存储设备 */
    }

    /* 执行读出固件 */
    return s_store_op_status.op->get_firmware();
}

/* 保存固件大小 (字节) */
static void mw_store_op_store_firmware_size(void)
{
    if (s_mw_prvt.stosel.is_set != MB_TRUE)
    {
        return;    /* 没有选择存储设备 */
    }

    /* 保存固件大小 */
    s_store_op_status.op->store_firmware_size();

    return;
}

/* 获得固件大小 (字节) */
static uint32_t mw_store_op_get_firmware_size(void)
{
    if (s_mw_prvt.stosel.is_set != MB_TRUE)
    {
        return 0;    /* 没有选择存储设备 */
    }

    /* 返回固件大小 */
    return s_store_op_status.op->get_firmware_size();
}

/* -------------------------- 启动前准备转接函数 --------------------------- */

/* 内存映射(针对从片外存储设备启动) */
static int mw_preboot_op_memory_mapped(void);
/* 加载固件 (往ROM写入) */
static int mw_preboot_op_load_firmware(uint32_t start_addr);
/* 系统去初始化 */
static void mw_preboot_op_system_deinit(uint32_t vtor);

/* preboot 的操作函数 */
preboot_op s_preboot_op = 
{
    .memory_mapped    = mw_preboot_op_memory_mapped,
    .load_firmware    = mw_preboot_op_load_firmware,
    .system_deinit    = mw_preboot_op_system_deinit,
};

/* 内存映射(针对从片外存储设备启动) */
static int mw_preboot_op_memory_mapped(void)
{
    if (s_mw_prvt.stosel.is_set != MB_TRUE)
    {
        return -1;    /* 没有选择存储设备 */
    }

    if (s_mw_prvt.stosel.select != STO_QSPIFLASH)
    {
        return -1;    /* 存储设备不是 STO_QSPIFLASH */
    }

    /* 将外部 QSPIFLASH 内存映射 */
    return s_store_op_status.op->memory_mapped();
}

/* 加载固件 (往ROM写入) */
static int mw_preboot_op_load_firmware(uint32_t start_addr)
{
    if (s_mw_prvt.stosel.is_set != MB_TRUE)
    {
        return -1;    /* 没有选择存储设备 */
    }

    /* 将外部 FLASH 中的固件数据加载到内部ROM */
//    return s_store_op_status.op->get_firmware();
    return -1;
}

/* 系统去初始化 */
static void mw_preboot_op_system_deinit(uint32_t vtor)
{
    uint32_t i;

    /* 禁止全局中断 */
    __set_PRIMASK(1);

    /* 关闭滴答定时器，复位到默认值 */
    SysTick->CTRL = 0;
    SysTick->LOAD = 0;
    SysTick->VAL  = 0;

    /* 关闭所有中断，清除所有中断挂起标志 */
    for (i = 0; i < 8; i++)
    {
        NVIC->ICER[i] = 0xFFFFFFFF;
        NVIC->ICPR[i] = 0xFFFFFFFF;
    }

    /* 偏移中断向量表 */
    SCB->VTOR  = vtor;

    /* 使能全局中断 */
    __set_PRIMASK(0);

    __set_CONTROL(0);

    return;
}

/* -------------------------- 用户交互处理函数 --------------------------- */
/* 选择人机交互通信通道 */
static int mw_hci_op_carrier_init(CMC_SELECT sel);
/* 等待用户主动打断事件 */
static MB_STATUS mw_hci_op_wait_abort(MB_STATUS SHOW_NOTICE);
/* 菜单显示 */
static int mw_hci_op_menu_show(void);
/* 处理用户输入选择 */
static hci_req * mw_hci_op_select_parse(void);
/* 反馈用户操作结果 */
static MB_STATUS mw_hci_op_response(MB_STATUS OP_RESULT);
/* 检测行为在指定时间后是否超时 */
static MB_STATUS mw_hci_op_check_is_timeout(uint32_t timeout);

/* hci 的操作函数 */
mw_hci_op s_mw_hci_op = 
{
    .carrier_select   = mw_hci_op_carrier_init,
    .wait_abort       = mw_hci_op_wait_abort,
    .menu_show        = mw_hci_op_menu_show,
    .select_parse     = mw_hci_op_select_parse,
    .response         = mw_hci_op_response,
    .check_is_timeout = mw_hci_op_check_is_timeout,
};

/* 初始化人机交互通信通道 */
static int mw_hci_op_carrier_init(CMC_SELECT sel)
{
    /* 判断数据载体是否可用 */
    if (s_cmc_op_status[sel].is_can_use != MB_TRUE)
    {
        return MB_FALSE;
    }

    /* 相同的选择执行一次 */
    if (s_mw_prvt.hcisel.select != sel)
    {
        /* 记录选择 */
        s_mw_prvt.hcisel.select = sel;
        /* 为人机交互指定数据载体 (硬件操作方法) */
        s_hci_op_status.op->carrier_init(s_cmc_op_status[sel].op);
        /* 标记已经设置选择 */
        s_mw_prvt.hcisel.is_set = MB_TRUE;
        return MB_TRUE;
    }

    return MB_FALSE;
}

/* 等待用户主动打断事件 */
static MB_STATUS mw_hci_op_wait_abort(MB_STATUS SHOW_NOTICE)
{
    if (s_mw_prvt.hcisel.is_set != MB_TRUE)
    {
        return MB_FALSE;    /* 没有选择数据设备 */
    }

    /* 菜单显示 */
    return s_hci_op_status.op->wait_abort(SHOW_NOTICE);
}

/* 菜单显示 */
static int mw_hci_op_menu_show(void)
{
    if (s_mw_prvt.hcisel.is_set != MB_TRUE)
    {
        return -1;    /* 没有选择数据设备 */
    }

    /* 菜单显示 */
    return s_hci_op_status.op->menu_show();
}

/* 处理用户输入选择 */
static hci_req * mw_hci_op_select_parse(void)
{
    if (s_mw_prvt.hcisel.is_set != MB_TRUE)
    {
        return NULL;    /* 没有选择数据设备 */
    }

    /* 返回用户输入的指令 */
    return s_hci_op_status.op->select_parse();
}

/* 反馈用户操作结果 */
static MB_STATUS mw_hci_op_response(MB_STATUS OP_RESULT)
{
    if (s_mw_prvt.hcisel.is_set != MB_TRUE)
    {
        return MB_FALSE_DEF;    /* 没有选择数据设备 */
    }

    /* 响应结果 */
    return s_hci_op_status.op->response(OP_RESULT);
}

/* 检测行为在指定时间后是否超时 */
static MB_STATUS mw_hci_op_check_is_timeout(uint32_t timeout)
{
    if (s_mw_prvt.hcisel.is_set != MB_TRUE)
    {
        return MB_FALSE_DEF;    /* 没有选择数据设备 */
    }

    return s_hci_op_status.op->check_is_timeout(timeout);
}

/* ======================================================================= */

/* 中间件控制块 */
mb_mw s_mb_mw = 
{
    .prot    = &s_mw_prot_op,
    .store   = &s_mw_store_op,
    .hci     = &s_mw_hci_op,
    .preboot = &s_preboot_op,
};

/* 中间件初始化 */
mb_mw *mb_mw_init(void)
{
    int ret;

    /* 注册设备的操作函数 */
    ret = mb_mw_dev_op_register();

    if (ret != 0)
    {
        return NULL;    /* CMC 或 STO 中有个没有设备可操作 */
    }

    /* 注册数据协议操作操作函数 */
    ret = mb_mw_prot_op_register();

    if (ret != 0)
    {
        return NULL;    /* 没有数据协议可以操作 */
    }

    /* 注册数据存储的操作函数 */
    ret = mb_mw_store_op_register();

    if (ret != 0)
    {
        return NULL;    /* 没有数据存储可以操作 */
    }

    /* 注册人机交互的操作函数 */
    ret = mb_mw_hci_op_register();

    if (ret != 0)
    {
        return NULL;    /* 没有数据存储可以操作 */
    }

    /* 返回中间控制块的控制句柄 */
    return &s_mb_mw;
}
